"""
The goal for objectmaker is to take an IOML string and generate an object.

Objectmaker needs to be aware of internal types from coffeetalk.protocol.types
it also needs a 'root' directory, or any number of directories, for generating user-defined objects.
"""

import copy
import sys

from coffeetalk.protocol import iotypes

class ObjectMaker(object):
    
    def __init__(self,paths=[]):
        
        for path in paths:
            sys.path.append(path)
        
        self.cachedtypes = {}
    
    def import_name(self,modulename,name):
        
        typename = ''.join((modulename,'.',name))
        if self.cachedtypes.has_key(typename):
            return self.cachedtypes[typename]
        try:
            module = __import__(modulename,globals(),locals(), [name])
        except ImportError:
            print 'Error importing %s as %s' % (modulename,name)
            return None
        newtype = getattr(module,name)
        self.cachedtypes[typename] = newtype
        return newtype

    def remove_type(self,typename):
        if self.cachedtypes.has_key(typename):
            del self.cachedtypes[typename]
    
    def make_object(self,element):
        if element.attribs.has_key('type'):
            elementtype = element.attribs['type']
            
            if elementtype.startswith('['):
                internaltype = elementtype[1:-1]
                if hasattr(iotypes,internaltype):
                    impclass = self.import_name("coffeetalk.protocol.iotypes",internaltype)
                    cls = None
                    try:
                        cls = impclass(name=element.name,value=element.attribs['value'])
                    except:
                        cls = impclass(name=element.name,**element.attribs)
                    return cls
                elif internaltype == 'List' and element.attribs.has_key('require'):
                    cls = iotypes.IOList(name=element.name,require=element.attribs['require'])
                    for key,value in element.childelements.iteritems():
                        cls[key] = self.make_object(value)
                    return cls
                else:
                    raise AttributeError('%s is not an internal type' % (elementtype))
            else:
                modulename,name = elementtype.rsplit('.',1)
                impclass = self.import_name(modulename,name)
                impattribs = copy.deepcopy(element.attribs)
                if impattribs.has_key('type'):
                    del impattribs['type']
                cls = impclass(name=element.name,**(impattribs))
                for key,value in element.childelements.iteritems():
                    cls.__setattr__(key,self.make_object(value))
                return cls
        else:
            cls = iotypes.IOList(name=element.name)
            for key,value in element.childelements.iteritems():
                cls[key] = self.make_object(value)
            return cls

if __name__ == '__main__':
    from coffeetalk.protocol import ioml
    hermespath = '/Users/mike/Documents/workspace/NowStream Phoenix/Applications/Mercury/mercury/types'
    iostring = """<ioml v="1.0">
    <h />
    <b>
        <i t="Yo">
            <i t="Users" type="%5BList%5D" require="%5BString%5D">
                <i t="Mike" type="%5BString%5D" value="5" />
                <i t="Hillary" type="%5BString%5D" value="5" />
            </i>
            <i t="Mike" type="com.NowStream.Monitoring.System" />
            <i t="Joe" type="com.NowStream.Monitoring.System" />
        </i>
    </b>
</ioml>
"""
    yiostring = """<ioml v="1.0">
    <h />
    <b>
        <i n="Yo">
            <i n="Users" />
            <i n="Mike" type="[Subscriber]" username="Joe" group="System" handler="yomama" />
            <i n="Authenticate" type="[Credentials]" username="mike" password="you" group="Users" />
            <i n="Joe" type="coffeetalk.server.types.Extension">
                <i n="Paths">
                    <i n="/Application/Chat/Foo/" />
                    <i n="/Application/Chat/Bar/" />
                </i>
            </i>
        </i>
    </b>
</ioml>
"""
    #print iostring
    
    #import coffeetalk.server.ionode
    i = ioml.IOML(iomlstring=yiostring, encoded=False)
    
    print i
    
    print i.bodyelement
    
    #for key,value in i.bodyelement.childelements.iteritems():
    #    print '%s:%r' % (key,value)
    om = ObjectMaker(paths=[hermespath])
    s = om.make_object(i.bodyelement)
#    
    print s
    print type(s)
    
    for key in s.keys():
        print 'Key: %s' % (key)
    for key,value in s.iteritems():
        print '%s:%s' % (key,str(value))
    for value in s.itervalues():
        print '%s' % (type(value))
    
    